''' Dado um arquivo como parametro com cada linha da forma:

NomeDaClasse ( Tipo a1 , Tipo a2 , (...) , Tipo an )
Ou comeca com $ se for abstrata.

Cria as classes para a arvore abstrata e a interface do visitor tambem.
Precisa reorganizar os arquivos nos packages/pastas corretos apos a criacao

Para usar deve dar o nome do arquivo:

python classes.py nomeDoArquivoComAsDefinicoes

'''

import sys

visitor = open('Visitor.java', 'w')

visitor.write('package visitor;\n')
visitor.write('import syntaxtree.*;\n')
visitor.write('public interface Visitor {\n\n')

for linha in open(sys.argv[1], 'r'):
    attr = linha.rstrip().replace(',', ' ').replace('(', ' ').replace(')', ' ').split()
    abstract = False
    if attr[0].startswith('$'):
        abstract = True
        attr[0] = attr[0].replace('$', '')
    fil = open (attr[0]+'.java', 'w')
    tipos = []
    atributos = []
    for i in range(len(attr)):
        if i == 0:
            continue
        if i % 2 == 0:
            atributos.append(attr[i])
        else:
            tipos.append(attr[i])
    print('\n')
    print(attr)
    print(tipos)
    print(atributos)
    fil.write('package syntaxtree;\n')
    fil.write('import visitor.Visitor;\n')
    fil.write('import visitor.TypeVisitor;\n')
    if not abstract:
        fil.write('public class ' + attr[0] + ' {\n')
    else:
        fil.write('public abstract class ' + attr[0] + ' {\n')
    fil.write('\n')
    if not abstract:
        for i in range(len(tipos)):
            fil.write('\tpublic ' + tipos[i] + ' ' + atributos[i] + ';\n')
        fil.write('\n\tpublic ' + attr[0] + linha.replace(attr[0], '').rstrip() + '{')
        fil.write('\n')
        for i in range(len(tipos)):
            fil.write('\t\t this.' + atributos[i] + ' = ' + atributos[i] + ';\n')
        fil.write('\t}\n\n')
        fil.write('\tpublic void accept (Visitor v) {\n')
        fil.write('\t\tv.visit(this);\n\t}\n')
        fil.write('\tpublic Type accept (TypeVisitor v) {\n')
        fil.write('\t\treturn v.visit(this);\n\t}\n')
        fil.write('}')
    else:
        fil.write('\tpublic abstract void accept (Visitor v);\n')
        fil.write('\tpublic abstract Type accept (TypeVisitor v);\n')
        fil.write('}')
    fil.close()
for linha in open(sys.argv[1], 'r'):
    classe = linha.split()[0]
    # $ = abstrata. nao precisa gerar
    if classe.startswith('$'):
        visitor.write('\n\t')
        visitor.write('// ' + classe.replace('$', '') + '\n')
    else:
        visitor.write('\tpublic void visit (' + classe + ' n);\n')
visitor.write('}')
visitor.close()
